﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace DARE
{
    /// <summary>
    /// Uniformize all the differents space partitioners.
    /// Can be used to implement a BSP tree, Octree...
    /// </summary>
    public interface IPartitioner
    {
        /// <summary>
        /// List of IPartitioner items after the call of Process.
        /// The items are not ordered.
        /// </summary>
        List<IPartitionerItem> Regular { get; }

        /// <summary>
        /// List of IPartitioner items orderered from back to front after the call of Process.
        /// </summary>
        List<IPartitionerItem> BackToFront { get; }

        /// <summary>
        /// List of IPartitioner items ordered from front to back after the call of Process.
        /// </summary>
        List<IPartitionerItem> FrontToBack { get; }

        /// <summary>
        /// Number of Regular items processed.
        /// Use "Regular" to get the list of items processed.
        /// </summary>
        int RegularNumber { get; }

        /// <summary>
        /// Number of back to front items processed.
        /// </summary>
        int BackToFrontNumber { get; }

        /// <summary>
        /// Number of front to back items processed.
        /// </summary>
        int FrontToBackNumber { get; }

        /// <summary>
        /// Add an item in the process lists. Each octree item is added in the list by this method.
        /// </summary>
        /// <param name="camPos">Camera's position.</param>
        /// <param name="item">Partitionner item to add in the process lists.</param>
        void AddProcessItem(Vector3 camPos, IPartitionerItem item);

        /// <summary>
        /// Draw the space partitioner in 3d if Show is true.
        /// Used to debug.
        /// </summary>
        void Draw();

        /// <summary>
        /// Show or not the space partitionner.
        /// Get if the partitionner is shown.
        /// Set if the partitionner is shown.
        /// </summary>
        bool Show { get; set; }

        /// <summary>
        /// Show or not all the collisions view boxes of each items in the space partitionner.
        /// Works only if "Show" is true.
        /// Get if the items are shown.
        /// Set if the items are shown.
        /// </summary>
        bool ShowItems { get; set; }

        FillMode ItemsFillMode { get; set; }

        /// <summary>
        /// The LOD range modify the distances between two differents LOD values.
        /// Get the LOD range.
        /// Set the LOD range.
        /// </summary>
        float LODRange { get; set; }

        /// <summary>
        /// Add an item in the space partitioner.
        /// </summary>
        /// <param name="item">Item to add.</param>
        /// <returns>Success or failure.</returns>
        bool AddItem(IPartitionerItem item);

        /// <summary>
        /// Remove an item from the partitioner.
        /// </summary>
        /// <param name="item">Item to remove.</param>
        /// <returns>Success or failure.</returns>
        bool RemoveItem(IPartitionerItem item);

        /// <summary>
        /// Remove all the items from the space partitioner.
        /// </summary>
        /// <returns>Success or failure. Success happens when there was at least one item removed.</returns>
        bool Clear();

        /// <summary>
        /// Process the items inside or intersected by all rendering cameras frustrum.
        /// The processed items are accessible throught the Regular / BackToFront and FrontToBack lists.
        /// </summary>
        /// <param name="cams">Rendering cameras list</param>
        void Process(List<CCamera> cams);

        /// <summary>
        /// Process the item closest to a point.
        /// The processed items are accessible trhought the Ragular / BackToFront and FrontToBack lists.
        /// WARNING, not working atm !
        /// <param name="pos">Position where to surch the nearest item.</param>
        /// </summary>
        void Process(Vector3 pos);

        /// <summary>
        /// Process the items inside or intersected by the frustrum.
        /// The processed items are accessible throught the Regular / BackToFront and FrontToBack lists.
        /// </summary>
        /// <param name="camPos">Camera position.</param>
        /// <param name="collider">Bounding frustrum.</param>
        void Process(Vector3 camPos, BoundingFrustum collider);

        /// <summary>
        /// Process the items inside or intersected by the given box.
        /// The processed items are accessible throught the Regular / BackToFront and FrontToBack lists.
        /// </summary>
        /// <param name="camPos">Camera position.</param>
        /// <param name="collider">Axis aligned bounding box.</param>
        void Process(Vector3 camPos, BoundingBox collider);

        /// <summary>
        /// Process the items inside or intersected by a sphere.
        /// The processed items are accessible throught the Regular / BackToFront and FrontToBack lists.
        /// </summary>
        /// <param name="camPos">Camera position.</param>
        /// <param name="collider">Bounding sphere.</param>
        void Process(Vector3 camPos, BoundingSphere collider);
    }
}
